package partition;

import config.Config;
import eval.LBEval;
import network.Network;
import network.Rule;
import verifier.Ports.ArrayPorts;
import verifier.Ports.PersistentPorts;
import verifier.util.BDDEngine;
import verifier.JiffyVerifier;
import verifier.util.Changes;

import java.util.*;

public class SubgraphPartition {
    private Network network;
    private Network subgraphNetwork;
    private List<Rule> rules;
    private JiffyVerifier verifier;
    private BDDEngine bddEngine;

    public SubgraphPartition(Network network, Network subgraphNetwork, List<Rule> rules, BDDEngine bddEngine) {
        this.network = network;
        this.subgraphNetwork = subgraphNetwork;
        this.rules = rules;
        this.bddEngine = bddEngine;
        if (Config.enablePD) {
            this.verifier = new JiffyVerifier(network, bddEngine, new PersistentPorts());
        } else {
            this.verifier = new JiffyVerifier(network, bddEngine, new ArrayPorts());
        }
    }

    public void run(boolean useFFMT) {
        long s = System.nanoTime();
        if (useFFMT) {
            Changes changes = verifier.insertMiniBatch(rules);
            this.verifier.update(changes);
        } else {
            for (Rule rule : rules) {
                Changes changes = verifier.insertMiniBatch(new ArrayList<>(Collections.singletonList(rule)));
                this.verifier.update(changes);
            }
        }
        long time = System.nanoTime() - s;
        System.out.println("useFFMT: " + useFFMT);
        System.out.println("$model: " + time);
        System.out.println("#rules: " + rules.size());
        System.out.println("#ECs in subgraph: " + verifier.predSize());
    }

    /**
     * input a set of rules from closed device, for early detection
     * @param rules
     */
    public void run(List<Rule> rules) {
        if (rules == null || rules.size() == 0) {
            return;
        }
        Changes changes = verifier.insertMiniBatch(rules);
        this.verifier.update(changes);
    }
    public void run(List<Rule> rules, boolean enableFFMT) {
        if (rules == null || rules.size() == 0) {
            return;
        }
        if (enableFFMT) {
            Changes changes = verifier.insertMiniBatch(rules);
            this.verifier.update(changes);
            this.verifier.printTime(rules.size());
        } else {
            for (Rule rule : rules) {
                Changes changes = verifier.insertMiniBatch(new ArrayList<>(Arrays.asList(rule)));
                this.verifier.update(changes);
            }
            this.verifier.printTime(rules.size());
        }
    }

    public BDDEngine getBddEngine() {
        return bddEngine;
    }

    public JiffyVerifier getVerifier() {
        return verifier;
    }

    public List<Rule> getRules() {
        return rules;
    }

    public Network getNetwork() {
        return network;
    }

    public void setRules(List<Rule> rules) {
        this.rules = rules;
    }

    public Network getSubgraphNetwork() {
        return subgraphNetwork;
    }
}